#include "Com.hpp"
#include "Log.hpp"
#include <strings.h>
#include "InetAddr.hpp"
#include <sys/wait.h>

using namespace LogModule;

class TcpServer : public NoCopy
{
    const static int defualtListenfd = -1;
    const static int listennum = 8;

public:
    TcpServer(uint16_t port)
        : _port(port), _listenfd(defualtListenfd), backlog(listennum), _len(0), _isrunning(false)
    {
        LOG(LogLevel::DEBUG) << "_port: " << _port;
    }

    int Init()
    {
        _listenfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_listenfd < 0)
        {
            LOG(LogLevel::FATAL) << "socket error";
            return SOCKET_ERR;
        }
        LOG(LogLevel::DEBUG) << "socket create success!";
        struct sockaddr_in server;
        bzero(&server, sizeof(server));
        server.sin_addr.s_addr = INADDR_ANY;
        server.sin_family = AF_INET;
        server.sin_port = htons(_port);
        _len = sizeof(server);

        int ret = bind(_listenfd, (struct sockaddr *)&server, sizeof(server));
        if (ret < 0)
        {
            LOG(LogLevel::FATAL) << "bind failed!";
            return BIND_ERR;
        }
        LOG(LogLevel::DEBUG) << "bind success!";
        int n = listen(_listenfd, backlog);
        if (n < 0)
        {
            LOG(LogLevel::FATAL) << "listen failed";
            return LISTEN_ERR;
        }
        LOG(LogLevel::DEBUG) << "listen success!";
        return OK;
    }

private:
    void Service(int sockfd, InetAddr &client)
    {
        char buffer[1024];
        while (true)
        {
            int rec_n = read(sockfd, buffer, sizeof(buffer));
            if (rec_n < 0)
            {
                LOG(LogLevel::ERROR) << "read failed";
                close(sockfd);
                break;
            }
            else if (0 == rec_n)
            {
                LOG(LogLevel::ERROR) << "writer close";
                close(sockfd);
                break;
            }
            else
            {
                buffer[rec_n] = '\0';
                LOG(LogLevel::DEBUG) << "read success";
                std::string sendmessage = "server say# ";
                sendmessage += buffer;
                int send_t = write(sockfd, sendmessage.c_str(), sendmessage.size());
                if (send_t < 0)
                {
                    LOG(LogLevel::ERROR) << "send " << client.GetIP() << " message failed";
                    continue;
                }

                LOG(LogLevel::ERROR) << "send " << client.GetIP() << " message success";
            }
        }
    }

public:
    class ThreadData
    {
    public:
        ThreadData(int fd, InetAddr &c, TcpServer &t)
            : sockfd(fd), client(c), tsvr(t)
        {
        }
        int sockfd;
        InetAddr &client;
        TcpServer &tsvr;
    };

    static void *Routine(void *args)
    {
        pthread_detach(pthread_self());
        if (args == nullptr)
        {
            LOG(LogLevel::FATAL) << "线程Routine函数失败";
            _exit(ROUTINE_ERR);
        }
        ThreadData *tptr = (ThreadData *)(args);
        tptr->tsvr.Service(tptr->sockfd, tptr->client);
        return nullptr;
    }

    void Run()
    {
        _isrunning = true;
        while (_isrunning)
        {
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            InetAddr client(peer);
            int sockfd = accept(_listenfd, (struct sockaddr *)&peer, &len);
            if (sockfd < 0)
            {
                LOG(LogLevel::FATAL) << "accept failed: " << client.GetIP();
                continue;
            }

            LOG(LogLevel::INFO) << "accept success!" << client.GetIP();

            // version 1 单进程版本
            //  Service(sockfd, client);

            // version 2 多进程版本
            //  int pid = fork();
            //  if(pid == 0)
            //  {
            //      //子进程
            //      close(_listenfd);
            //      if(fork() != 0)
            //      {
            //          exit(OK);
            //      }
            //      Service(sockfd , client);
            //  }
            //  else
            //  {
            //      //父进程
            //      waitpid(pid , nullptr , 0);
            //  }

            // version 3 多线程版本
            pthread_t tid;
            ThreadData data(sockfd, client, *this);
            pthread_create(&tid, nullptr, Routine, &data);
        }
    }

private:
    uint16_t _port;
    int _listenfd;
    socklen_t _len;
    int backlog;
    bool _isrunning;
};